﻿using System;
using System.Linq;
using System.Web.Mvc;
using MvcContrib.Pagination;
using Project.DAL.Repository;
using Project.Domain.Entities;

namespace Project.WebUI.Areas.Admin.Controllers
{
    public class MatchController : Controller
    {        
        #region "private"
        private readonly IBetDetailRepository _betDetailRepository;
        private readonly IUserRepository _userRepository;        
        private readonly ISoccerTeamRepository _soccerTeamRepository;        
        private readonly IMatchesRepository _matchesRepository;
        private readonly ILeagueRepository _leagueRepository;
        private readonly IBetRepository _betRepository;
        private readonly IUserbetRepository _userbetRepository;        

        public MatchController(
            IUserRepository userRepository,
            ISoccerTeamRepository soccerTeamRepository,              
            IMatchesRepository matchesRepository,
            ILeagueRepository leagueRepository,   
            IBetRepository betRepository,    
            IUserbetRepository userbetRepository, 
            IBetDetailRepository betDetailRepository)
        {
            _userRepository = userRepository;            
            _soccerTeamRepository = soccerTeamRepository;            
            _matchesRepository = matchesRepository;
            _leagueRepository = leagueRepository;
            _betRepository = betRepository;
            _userbetRepository = userbetRepository;
            _betDetailRepository = betDetailRepository;
        }

        #endregion        

        #region Index
        public  ActionResult Index()
        {
            return View();
        }
        #endregion

        #region LoadAjax
        public ActionResult LoadAjax(int page)
        {
            var listMatch = _matchesRepository.GetMany(null,
                                                      m =>
                                                      m.OrderBy(t => t.IsPlay).ThenByDescending(i=>i.Status),
                                                      "HomeTeam,AwayTeam,League");
            ViewBag.result = listMatch.Count();
            ViewBag.page = page;
            if (page == 1)
            {
                ViewBag.start = 0;
            }
            else
            {
                ViewBag.start = (page - 1) * 10;
            }
            return PartialView("_MainContent", listMatch.AsPagination(page, 10));
        }
        #endregion
        
        #region "UpdateStatus"
        public ActionResult UpdateStatus(int id, int status)
        {
            var match = _matchesRepository.GetById(id);
            var league = _leagueRepository.GetById(match.LeagueId);
            var homeTeam = _soccerTeamRepository.GetById(match.HomeTeamId);
            var awayTeam = _soccerTeamRepository.GetById(match.AwayTeamId);
            if (status == 1)
            {                
                match.Status = false;
                _matchesRepository.SaveChanges();
                if (league.Matches.Count(m => m.IsPlay == 0 && m.Status) == 0)
                {
                    league.IsPlay = false;
                }
                _leagueRepository.SaveChanges();
                var listMatchOfHomeTeam = _matchesRepository
                    .GetMany(m => m.HomeTeamId.Equals(homeTeam.SoccerTeamId)
                        && m.Status
                        && m.IsPlay == 0);
                if (!listMatchOfHomeTeam.Any())
                {
                    homeTeam.Status = false;
                }
                var listMatchOfAwayTeam = _matchesRepository
                    .GetMany(m => m.AwayTeamId.Equals(awayTeam.SoccerTeamId)
                        && m.Status
                        && m.IsPlay == 0);

                if (!listMatchOfAwayTeam.Any())
                {
                    awayTeam.Status = false;
                }
                _soccerTeamRepository.SaveChanges();
                ViewBag.status = false;
                ViewBag.id = id;
                ViewBag.controller = "Match";
                return PartialView("_UpdateStatus");
            }
            
            match.Status = true;            
            league.IsPlay = true;
            homeTeam.Status = true;
            awayTeam.Status = true;
            _matchesRepository.SaveChanges();
            _leagueRepository.SaveChanges();
            _soccerTeamRepository.SaveChanges();
            ViewBag.status = true;
            ViewBag.id = id;
            ViewBag.controller = "Match";
            return PartialView("_UpdateStatus");
        }

        #endregion

        #region Modify Obj
        public ActionResult Modify(int? id)
        {            
            if (Session["admin"] == null)
                return RedirectToAction("Login", "DashBoard");
            if (id != null)
            {
                var obj = _matchesRepository.GetById((int)id);
                var leagueId = obj.LeagueId;
                var homeTeamId = obj.HomeTeamId;
                var awayTeamId = obj.AwayTeamId;
                ViewBag.Id = id;
                if (ViewBag.league == null)
                {
                    var listLeague = _leagueRepository.GetMany(null, l => l.OrderByDescending(n => n.NameLeague));
                    ViewBag.league = new SelectList(listLeague, "LeagueId", "NameLeague", leagueId);
                }

                if (ViewBag.homeTeam == null)
                {
                    ViewBag.homeTeam = new SelectList(_soccerTeamRepository.GetAll(),"SoccerTeamId",
                                                      "TeamName", homeTeamId);
                }

                if (ViewBag.awayTeam == null)
                {
                    ViewBag.awayTeam = new SelectList(_soccerTeamRepository.GetAll(), "SoccerTeamId",
                                                      "TeamName", awayTeamId);
                }
                return View(obj);
            }
            if(ViewBag.league==null)
            {
                var listLeague = _leagueRepository.GetMany(null, l => l.OrderByDescending(n => n.NameLeague));
                ViewBag.league = new SelectList(listLeague, "LeagueId", "NameLeague");
            }

            if(ViewBag.homeTeam==null)
            {
                ViewBag.homeTeam = new SelectList(_soccerTeamRepository.GetAll(), "SoccerTeamId", "TeamName");
            }

            if (ViewBag.awayTeam == null)
            {
                ViewBag.awayTeam = new SelectList(_soccerTeamRepository.GetAll(), "SoccerTeamId",
                                                  "TeamName");
            }
            return View();
        }

        [HttpPost]
        public ActionResult Modify(int? id, FormCollection obj)
        {
            var homeId = Convert.ToInt32(obj["homeId"]);
            var awayId = Convert.ToInt32(obj["awayId"]);
            var leagueId = Convert.ToInt32(obj["leagueId"]);
            var startTime = Convert.ToDateTime(obj["date"]);
            var timePlay = obj["time"];
            var homeScore = Convert.ToDecimal(obj["homeScore"]);
            var awayScore = Convert.ToDecimal(obj["awayScore"]);

            if (ViewBag.homeTeam == null)
            {
                ViewBag.homeTeam = new SelectList(_soccerTeamRepository.GetAll(), "SoccerTeamId", "TeamName", "---Select team---");
            }

            if (ViewBag.league == null)
            {
                var listLeague = _leagueRepository.GetMany(l => l.IsPlay, l => l.OrderByDescending(n => n.NameLeague));
                ViewBag.league = new SelectList(listLeague, "LeagueId", "NameLeague", "---Select League---");
            }
            if (id != null)
            {
                var match = _matchesRepository.GetById((int)id);                                
                if (match != null)
                {
                    if (match.IsPlay == 2)
                    {
                        //return 2 if Match inplay
                        return Content("2");
                    }
                    if (match.IsPlay == 1)
                    {
                        return Content("3");
                    }
                    match.HomeTeamId = homeId;
                    match.AwayTeamId = awayId;
                    match.LeagueId = leagueId;
                    match.StartTime = startTime;
                    match.TimePlay = timePlay;
                    match.HomeScore = homeScore;
                    match.AwayScore = awayScore;
                    _matchesRepository.SaveChanges();
                    _leagueRepository.SaveChanges();
                    //sucessfull
                    return Content("1");
                }
                //not found
                return Content("0");
            }
            else
            {
                var match = new Match()
                                {
                                    HomeTeamId = homeId,
                                    AwayTeamId = awayId,
                                    LeagueId = leagueId,
                                    Status = false,
                                    StartTime = startTime,
                                    TimePlay = timePlay,
                                    CreatedTime = DateTime.Now,
                                    EndTime = DateTime.Now,
                                    IsPlay = 0,//pending
                                    HomeScore = 0,
                                    AwayScore = 0
                                };
                try
                {
                    _matchesRepository.Add(match);
                    _matchesRepository.SaveChanges();
                    _leagueRepository.SaveChanges();
                    //sucessfull
                    return Content("1");
                }
                catch (Exception ex)
                {
                    //Error
                    return Content(ex.ToString());
                }
            }
        }
        #endregion

        #region Delete
        public ActionResult Delete(int id)
        {                        
            var statusAction = _matchesRepository.Delete(m => m.MatchId.Equals(id));
            _matchesRepository.SaveChanges();
            return Content(statusAction ? "1" : "0");
        }
        #endregion

        #region InPlay
        public ActionResult InPlay(int id)
        {
            var match = _matchesRepository.GetById(id);
            if(match.Status==false)
            {
                return Content("lock");
            }
            switch (match.IsPlay)
            {
                case 2:
                    return Content("2");
                case 1:
                    return Content("1");
                default:
                    match.IsPlay = 2;
                    _matchesRepository.SaveChanges();

                    var leagueId = match.LeagueId;
                    var league = _leagueRepository.GetById(leagueId);
                    var listmMatchSameLeague = _matchesRepository.GetMany(m => m.LeagueId == leagueId & m.IsPlay == 0);
                    if (!listmMatchSameLeague.Any())
                    {
                        league.IsPlay = false;
                        _leagueRepository.SaveChanges();
                    }

                    var listBetOfMatch = _betRepository.GetMany(b => b.MatchId.Equals(id));
                    foreach (var bet in listBetOfMatch)
                    {
                        var lisBetDetailOfBet = _betDetailRepository.GetMany(bd => bd.BetId.Equals(bet.BetId));
                        foreach (var betDetail in lisBetDetailOfBet)
                        {
                            betDetail.Status = false;
                        }
                        bet.Status = false;
                    }
                    _betDetailRepository.SaveChanges();
                    _betRepository.SaveChanges();
                    return Content("sucess");
            }
        }
        #endregion

        #region EndPlay
        public decimal CountFree(decimal source )
        {
            var free = (source*5)/100;
            return free;
        }

        public  ActionResult EndPlayAble(int id)
        {
            var match = _matchesRepository.GetById(id);
            return Content(match.IsPlay == 1 ? "closed" : "inplay");
        }

        public  ActionResult EndPlay(int id)
        {
            var match = _matchesRepository.GetById(id);
            return match.IsPlay == 1 ? View("Index") : View(match);
        }
        [HttpPost]
        public ActionResult EndPlay(int id, FormCollection obj)
        {
            var homeScore = Convert.ToInt32(obj["homeScore"]);
            var awayScore = Convert.ToInt32(obj["awayScore"]);
            var match = _matchesRepository.GetById(id);
            match.HomeScore = homeScore;
            match.AwayScore = awayScore;
            match.EndTime = DateTime.Now;
            match.IsPlay = 1;
            match.Status = false;

            //list all bet of matches
            var listBetOfMatchId = _betRepository
                .GetMany(bet => bet.MatchId == match.MatchId);
            foreach (var bet in listBetOfMatchId)
            {
                var maxBet = bet.MaxBet;
                var currentBet = bet.CurrentBet;
                var winBet = 0M;
                var reFund = 0M;
                //update bet
                bet.ScoreHomeAfter = homeScore;
                bet.ScoreAwayAfter = awayScore;

                //list all userbet has status=false;
                var listUserBetNotTrueOfBet =
                    _userbetRepository.GetMany(
                        userbetnotTrueofbet =>
                        userbetnotTrueofbet.BetDetail.BetId == bet.BetId && userbetnotTrueofbet.Status == false);

                //del all userbet has status=false;
                foreach (var item in listUserBetNotTrueOfBet)
                {
                    _userbetRepository.Delete(item);
                    _userbetRepository.SaveChanges();
                }

                switch (bet.Type)
                {
                    //bet 3way : win,draw,lose
                    case 1:
                        {
                            //list all userbet has status=true and child of bet has type=1
                            var listUserBetOfBet1 =
                                _userbetRepository.GetMany(ub =>
                                                           ub.BetDetail.BetId == bet.BetId && ub.Status &&
                                                           ub.BetDetail.Bet.Type == 1, null, "BetDetail");
                            var subscore = Convert.ToInt32(bet.ScoreHomeAfter - bet.ScoreAwayAfter);
                            foreach (var userbet in listUserBetOfBet1)
                            {
                                var userId = userbet.UserId;
                                var user = _userRepository.GetById(userId);
                                // if home win
                                if (subscore > 0)
                                {
                                    //update balance for userbet home
                                    if (userbet.BetDetail.Type == 1)
                                    {
                                        userbet.UserWin = (userbet.Odds*userbet.Stake) -
                                                          CountFree(userbet.Odds*userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;
                                        maxBet = maxBet - (userbet.Odds*userbet.Stake);
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds*userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                                //draw win
                                else if (subscore == 0)
                                {
                                    //update balance for userbet draw
                                    if (userbet.BetDetail.Type == 2)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;                                        
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                                    //away win
                                else
                                {
                                    //update balance for userbet away
                                    if (userbet.BetDetail.Type == 3)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;
                                        maxBet = maxBet - (userbet.Odds*userbet.Stake);
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                            }
                        }
                        break;
                        //bet 3way handicap : chap truoc gom co win,draw,lose
                    case 2:
                        {
                            //list all userbet has status=true and child of bet has type=1
                            var listUserBetOfBet2 =
                                _userbetRepository.GetMany(ub =>
                                                           ub.BetDetail.BetId == bet.BetId && ub.Status &&
                                                           ub.BetDetail.Bet.Type == 2, null, "BetDetail");
                            //subscore
                            var subscore =
                                Convert.ToDecimal((bet.ScoreHomeAfter + bet.ScoreHomeBefore) -
                                                  (bet.ScoreAwayAfter + bet.ScoreAwayBefore));
                            foreach (var userbet in listUserBetOfBet2)
                            {
                                var userId = userbet.UserId;
                                var user = _userRepository.GetById(userId);
                                //home win
                                if (subscore > 0)
                                {
                                    //update balance for userbet home
                                    if (userbet.BetDetail.Type == 1)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;                                        
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                                    //draw win
                                else if (subscore == 0)
                                {
                                    //update balance for userbet draw
                                    if (userbet.BetDetail.Type == 2)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;                                        
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                                    //away win
                                else
                                {
                                    //update balance for userbet home
                                    if (userbet.BetDetail.Type == 3)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;                                        
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                            }
                        }
                        break;
                        //Asian Handicap chap truoc chi co win,lose
                    case 3:
                        {
                            //list all userbet has status=true and child of bet has type=1
                            var listUserBetOfBet3 =
                                _userbetRepository.GetMany(ub =>
                                                           ub.BetDetail.BetId == bet.BetId && ub.Status &&
                                                           ub.BetDetail.Bet.Type == 3, null, "BetDetail");
                            var subscore =
                                Convert.ToDecimal((bet.ScoreHomeAfter + bet.ScoreHomeBefore) -
                                                  (bet.ScoreAwayAfter + bet.ScoreAwayBefore));
                            foreach (var userbet in listUserBetOfBet3)
                            {
                                var userId = userbet.UserId;
                                var user = _userRepository.GetById(userId);
                                //home win
                                if (subscore > 0)
                                {
                                    //update balance for userbet home
                                    if (userbet.BetDetail.Type == 1)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;                                        
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                                //away win
                                if (subscore < 0)
                                {
                                    //update balance for userbet home
                                    if (userbet.BetDetail.Type == 2)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;
                                        maxBet = maxBet - (userbet.Odds*userbet.Stake);
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                            }
                        }
                        break;
                    //under/over :duoi tren.
                    case 4:
                        {
                            //list all userbet has status=true and child of bet has type=1
                            var listUserBetOfBet4 =
                                _userbetRepository.GetMany(ub =>
                                                           ub.BetDetail.BetId == bet.BetId && ub.Status &&
                                                           ub.BetDetail.Bet.Type == 4, null, "BetDetail");
                            var sumscore = Convert.ToInt32(bet.ScoreHomeAfter + bet.ScoreAwayAfter);
                            foreach (var userbet in listUserBetOfBet4)
                            {
                                var userId = userbet.UserId;
                                var user = _userRepository.GetById(userId);
                                //under
                                if (userbet.BetDetail.Type == 1)
                                {
                                    //least than 
                                    if (userbet.BetDetail.RateUnderOver > sumscore)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                           CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;                                        
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                                //over
                                else
                                {
                                    if (sumscore < userbet.BetDetail.RateUnderOver)
                                    {
                                        userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                        userbet.IsWin = 1;
                                        user.Balance += userbet.UserWin + userbet.Stake;                                        
                                    }
                                    else
                                    {
                                        userbet.IsWin = 2;
                                        userbet.UserWin = 0;
                                        reFund += userbet.Odds * userbet.Stake;
                                        winBet = winBet + (userbet.Odds*userbet.Stake) -
                                                 CountFree(userbet.Odds*userbet.Stake);
                                    }
                                }
                            }
                        }
                        break;
                    //exact score: win,lose
                    default:
                        //list all userbet has status=true and child of bet has type=1
                        var listUserBetOfBet5 =
                            _userbetRepository.GetMany(ub =>
                                                       ub.BetDetail.BetId == bet.BetId && ub.Status &&
                                                       ub.BetDetail.Bet.Type == 5, null, "BetDetail");
                        foreach (var userbet in listUserBetOfBet5)
                        {
                            var userId = userbet.UserId;
                            var user = _userRepository.GetById(userId);
                            //exacterly 
                            if (userbet.BetDetail.Bet.ScoreHomeBefore == bet.ScoreHomeBefore &&
                                userbet.BetDetail.Bet.ScoreAwayBefore == bet.ScoreAwayBefore)
                            {
                                userbet.UserWin = (userbet.Odds * userbet.Stake) -
                                                          CountFree(userbet.Odds * userbet.Stake);
                                userbet.IsWin = 1;
                                user.Balance += userbet.UserWin + userbet.Stake;                                
                            }
                            else
                            {
                                userbet.IsWin = 2;
                                userbet.UserWin = 0;
                                reFund += userbet.Odds * userbet.Stake;
                                winBet = winBet + (userbet.Odds*userbet.Stake) -
                                         CountFree(userbet.Odds*userbet.Stake);
                            }
                        }
                        break;
                }
                var userHasBet = _userRepository.GetById(bet.UserId);
                userHasBet.Balance += winBet + currentBet + reFund;
            }
            _matchesRepository.SaveChanges();
            _userRepository.SaveChanges();
            _userbetRepository.SaveChanges();
            return Content("1");
        }

        #endregion

    }
}
